package org.jeecg.access.platform.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.access.constant.PlatformType;
import org.jeecg.access.entity.PlatformAccount;
import org.jeecg.access.platform.entity.BaseUserInfo;
import org.jeecg.access.platform.entity.BaseWorkData;
import org.jeecg.access.platform.entity.WbUserInfo;
import org.jeecg.access.platform.entity.WbWorksData;
import org.jeecg.access.platform.mapper.WbUserInfoMapper;
import org.jeecg.access.platform.mapper.WbWorksDataMapper;
import org.jeecg.access.platform.service.PlatformHandler;
import org.jeecg.access.platform.util.HttpRequestUtil;
import org.jeecg.access.platform.util.JsonParserUtils;
import org.jeecg.access.service.PlatformAccountService;
import org.jeecg.util.DateTimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 微博数据获取服务实现类
 * 统一重试决策器逻辑，校验核心数据节点有效性，不使用流式/函数式编程
 * 统一使用JsonParserUtils解析JSON
 */
@Slf4j
@Service
public class WbGetDataServiceImpl extends AbstractGetDataServiceImpl implements PlatformHandler {

    private final WbUserInfoMapper userInfoMapper;
    private final WbWorksDataMapper worksDataMapper;

    private final PlatformAccountService platformAccountService;

    @Value("${more.token}")
    private String token;
    @Value("${more.wb.userDetail}")
    private String userDetailUrl;
    @Value("${more.wb.userPost}")
    private String userPostUrl;
    @Value("${batch.size:100}")
    private int userBatchSize;
    @Value("${works.batch.size:500}")
    private int worksBatchSize;
    // 最大分页限制
    private static final int MAX_PAGE_LIMIT = 20;

    /**
     * 构造方法：注入依赖并调用父类构造
     */
    @Autowired
    public WbGetDataServiceImpl(
            WbUserInfoMapper userInfoMapper,
            WbWorksDataMapper worksDataMapper,
            HttpRequestUtil httpRequestUtil,
            ObjectMapper objectMapper,
            PlatformAccountService platformAccountService
    ) {
        super(httpRequestUtil, objectMapper);
        this.userInfoMapper = userInfoMapper;
        this.worksDataMapper = worksDataMapper;
        this.platformAccountService = platformAccountService;
    }

    // ========================== 用户信息同步实现 ==========================

    /**
     * 获取微博用户列表
     */
    @Override
    protected List<? extends BaseUserInfo> fetchUserInfoList() {
        List<WbUserInfo> userInfos = userInfoMapper.getUserInfos();
        return userInfos != null ? userInfos : new ArrayList<>();
    }

    /**
     * 为单个用户创建请求头
     */
    @Override
    protected Map<String, String> createUserRequestHeaders(BaseUserInfo user) {
        Map<String, String> headers = new HashMap<>(2);
        headers.put("Content-Type", "application/json");
        headers.put("Authorization", token);
        return headers;
    }

    /**
     * 为单个用户组装请求报文
     */
    @Override
    protected String buildUserRequestData(BaseUserInfo user) {
        if (!(user instanceof WbUserInfo)) {
            log.error("用户类型错误，无法构建请求报文");
            return null;
        }
        WbUserInfo wbUser = (WbUserInfo) user;

        Map<String, Object> requestBody = new HashMap<>(3);
        requestBody.put("uid", wbUser.getUserId());
        requestBody.put("share_text", "");
        requestBody.put("proxy", "");

        try {
            return objectMapper.writeValueAsString(requestBody);
        } catch (Exception e) {
            log.error("序列化用户请求参数失败", e);
            return null;
        }
    }

    /**
     * 获取用户信息API的URL
     */
    @Override
    protected String getUserApiUrl(BaseUserInfo user) {
        return userDetailUrl;
    }

    /**
     * 获取用户信息的请求方法
     */
    @Override
    protected String getUserRequestMethod() {
        return "POST";
    }

    /**
     * 创建用户信息请求的重试决策器（增强版）
     * 校验逻辑：
     * 1. HTTP状态码为5xx时重试
     * 2. 响应为空或非JSON格式时重试
     * 3. 核心数据节点（data）无效时重试（后续解析必需）
     */
    @Override
    protected HttpRequestUtil.RetryDecision createUserRetryDecision(BaseUserInfo user) {
        return new WbUserRetryDecision();
    }

    /**
     * 微博用户信息重试决策器
     */
    private class WbUserRetryDecision implements HttpRequestUtil.RetryDecision {
        @Override
        public boolean needRetry(int responseCode, String response) {
            // 1. HTTP状态码校验（5xx错误重试）
            if (responseCode >= 500 && responseCode < 600) {
                log.debug("用户请求HTTP 5xx错误({})，需要重试", responseCode);
                return true;
            }

            // 2. 响应为空或非JSON校验
            if (response == null || response.trim().isEmpty()) {
                log.debug("用户请求响应为空，需要重试");
                return true;
            }
            if (response.contains("<html>") || response.contains("<body>")) {
                log.debug("用户请求返回HTML内容（非JSON），需要重试");
                return true;
            }

            // 3. 核心数据节点校验（后续解析需使用data节点）
            try {
                // 校验业务状态
                String msg = JsonParserUtils.getStringValueFromString(response, "msg");
                if (!"success".equals(msg)) {
                    log.debug("用户请求业务响应失败（msg={}），需要重试", msg);
                    return true;
                }

                // 校验data节点
                Boolean isDataValid = JsonParserUtils.isNodeValid(response, "data");
                if (isDataValid == null || !isDataValid) {
                    log.debug("用户请求缺少有效data节点，需要重试");
                    return true;
                }
            } catch (Exception e) {
                log.error("解析用户响应失败，需要重试", e);
                return true;
            }

            return false;
        }
    }

    /**
     * 从响应报文中解析数据并组装用户信息
     */
    @Override
    protected BaseUserInfo parseUserResponse(BaseUserInfo originalUser, String response) {
        if (!(originalUser instanceof WbUserInfo)) {
            log.error("用户类型错误，无法解析响应数据");
            return null;
        }
        WbUserInfo wbUser = (WbUserInfo) originalUser;

        try {
            // 更新用户基础信息
            wbUser.setName(JsonParserUtils.getStringValueFromString(response, "data.screen_name"));
            wbUser.setDescription(JsonParserUtils.getStringValueFromString(response, "data.description"));
            wbUser.setFollowCount(JsonParserUtils.getIntValueFromString(response, "data.follow_count"));
            wbUser.setWorksCount(JsonParserUtils.getIntValueFromString(response, "data.statuses_count"));

            // 特殊处理粉丝数字段（可能包含"万"、"亿"单位）
            String followersCountStr = JsonParserUtils.getStringValueFromString(response, "data.followers_count");
            wbUser.setFollowersCount(parseFollowersCount(followersCountStr));

            return wbUser;
        } catch (Exception e) {
            log.error("解析用户响应数据失败", e);
            return null;
        }
    }

    /**
     * 批量更新用户信息
     */
    @Override
    protected void batchUpdateUserInfo(List<? extends BaseUserInfo> userInfos) {
        if (userInfos.isEmpty()) {
            log.info("没有需要更新的微博用户信息");
            return;
        }

        List<WbUserInfo> wbUsers = new ArrayList<>(userInfos.size());
        for (int i = 0; i < userInfos.size(); i++) {
            BaseUserInfo user = userInfos.get(i);
            if (user instanceof WbUserInfo) {
                wbUsers.add((WbUserInfo) user);
            } else {
                log.warn("跳过非微博用户类型的数据，索引：{}", i);
            }
        }

        if (!wbUsers.isEmpty()) {
            // 分批处理
            for (int i = 0; i < wbUsers.size(); i += userBatchSize) {
                int end = Math.min(i + userBatchSize, wbUsers.size());
                List<WbUserInfo> batch = new ArrayList<>();
                for (int j = i; j < end; j++) {
                    batch.add(wbUsers.get(j));
                }
                userInfoMapper.batchUpSert(batch);
                log.info("批量更新微博用户信息，批次 {} - {}，共 {} 条", i, end - 1, batch.size());
            }
            log.info("批量更新微博用户信息完成，总计 {} 条", wbUsers.size());
        }
    }

    // ========================== 作品数据同步实现 ==========================

    /**
     * 创建作品数据请求的重试决策器（增强版）
     * 校验逻辑：
     * 1. HTTP状态码为5xx时重试
     * 2. 响应为空或非JSON格式时重试
     * 3. 核心数据节点（data、data.data、cards）无效时重试（后续解析必需）
     */
    @Override
    protected HttpRequestUtil.RetryDecision createWorkRetryDecision(BaseWorkData workData) {
        return new WbWorkRetryDecision();
    }

    /**
     * 微博作品重试决策器
     */
    private class WbWorkRetryDecision implements HttpRequestUtil.RetryDecision {
        @Override
        public boolean needRetry(int responseCode, String response) {
            // 1. HTTP状态码校验（5xx错误重试）
            if (responseCode >= 500 && responseCode < 600) {
                log.debug("作品请求HTTP 5xx错误({})，需要重试", responseCode);
                return true;
            }

            // 2. 响应为空或非JSON校验
            if (response == null || response.trim().isEmpty()) {
                log.debug("作品请求响应为空，需要重试");
                return true;
            }
            if (response.contains("<html>") || response.contains("<body>")) {
                log.debug("作品请求返回HTML内容（非JSON），需要重试");
                return true;
            }

            // 3. 核心数据节点校验（后续解析需使用）
            try {
                // 校验业务状态
                String msg = JsonParserUtils.getStringValueFromString(response, "msg");
                if (!"success".equals(msg)) {
                    log.debug("作品请求业务响应失败（msg={}），需要重试", msg);
                    return true;
                }

                // 校验嵌套数据节点
                Boolean isDataValid = JsonParserUtils.isNodeValid(response, "data");
                if (isDataValid == null || !isDataValid) {
                    log.debug("作品请求缺少data节点，需要重试");
                    return true;
                }

                Boolean isDataPersonValid = JsonParserUtils.isNodeValid(response, "data.data");
                if (isDataPersonValid == null || !isDataPersonValid) {
                    log.debug("作品请求缺少data.data节点，需要重试");
                    return true;
                }

                // 校验作品列表节点
                Integer cardsLength = JsonParserUtils.getListLength(response, "data.data.cards");
                if (cardsLength == null || cardsLength <= 0) {
                    log.debug("作品请求核心节点data.data.cards无效，需要重试");
                    return true;
                }
            } catch (Exception e) {
                log.error("解析作品响应失败，需要重试", e);
                return true;
            }

            return false;
        }
    }

    /**
     * 获取用户的所有作品（适配父类参数和重试逻辑）
     */
    @Override
    protected List<? extends BaseWorkData> fetchUserAllWorks(BaseUserInfo userInfo, String nowTime,Integer dataNum) throws Exception {
        if (!(userInfo instanceof WbUserInfo)) {
            log.error("用户类型错误，无法获取微博作品");
            return new ArrayList<>();
        }
        WbUserInfo wbUser = (WbUserInfo) userInfo;
        Map<String, String> headers = createHeaders(userInfo);

        return fetchUserWorks(wbUser, headers, nowTime);
    }


    /**
     * 批量更新作品数据
     */
    @Override
    protected void batchUpdateWorksData(List<? extends BaseWorkData> worksData) {
        if (worksData.isEmpty()) {
            log.info("没有需要更新的微博作品数据");
            return;
        }

        List<WbWorksData> wbWorks = new ArrayList<>(worksData.size());
        for (int i = 0; i < worksData.size(); i++) {
            BaseWorkData work = worksData.get(i);
            if (work instanceof WbWorksData) {
                wbWorks.add((WbWorksData) work);
            } else {
                log.warn("跳过非微博作品类型的数据，索引：{}", i);
            }
        }

        if (!wbWorks.isEmpty()) {
            // 分批处理
            for (int i = 0; i < wbWorks.size(); i += worksBatchSize) {
                int end = Math.min(i + worksBatchSize, wbWorks.size());
                List<WbWorksData> batch = new ArrayList<>();
                for (int j = i; j < end; j++) {
                    batch.add(wbWorks.get(j));
                }
                worksDataMapper.batchUpSert(batch);
                log.info("批量更新微博作品数据，批次 {} - {}，共 {} 条", i, end - 1, batch.size());
            }
            log.info("批量更新微博作品数据完成，总计 {} 条", wbWorks.size());
        }
    }

    /**
     * 构造作品相关API的请求头
     */
    @Override
    protected Map<String, String> createHeaders(BaseUserInfo userInfo) {
        Map<String, String> headers = new HashMap<>(2);
        headers.put("Content-Type", "application/json");
        headers.put("Authorization", token);
        return headers;
    }

    // ========================== 自定义业务方法（适配优化） ==========================

    /**
     * 获取用户作品列表（使用增强的重试决策器）
     */
    private List<WbWorksData> fetchUserWorks(WbUserInfo user, Map<String, String> headers, String nowTime) throws IOException {
        String userId = user.getUserId();
        if (userId == null || userId.isEmpty()) {
            log.warn("用户ID为空，无法获取作品");
            return new ArrayList<>();
        }

        List<WbWorksData> allWorksData = new ArrayList<>();
        String currentSinceId = null;
        int page = 0;
        boolean hasMore = true;

        // 分页获取作品数据
        while (page < MAX_PAGE_LIMIT && hasMore) {
            page++;
            String response = requestUserPostPage(userId, headers, currentSinceId, nowTime);
            if (response == null) {
                break;
            }

            List<WbWorksData> pageData = parseWorksPage(response, user, nowTime);
            if (pageData.isEmpty()) {
                hasMore = false;
            } else {
                // 传统循环添加元素（非流式）
                for (int i = 0; i < pageData.size(); i++) {
                    allWorksData.add(pageData.get(i));
                }
                log.info("微博用户 {} 第{}页获取{}条作品数据", userId, page, pageData.size());
            }

            // 获取下一页游标
            currentSinceId = parseSinceId(response);
            if (currentSinceId == null || currentSinceId.isEmpty()) {
                hasMore = false;
            }
        }

        return allWorksData;
    }

    /**
     * 请求单页作品数据（使用作品重试决策器）
     */
    private String requestUserPostPage(String userId, Map<String, String> headers, String sinceId, String nowTime) throws IOException {
        long startTime = System.currentTimeMillis();

        Map<String, Object> requestBody = new HashMap<>(4);
        requestBody.put("uid", userId);
        requestBody.put("share_text", "");
        requestBody.put("since_id", sinceId != null ? sinceId : "");
        requestBody.put("proxy", "");

        String requestJson;
        try {
            requestJson = objectMapper.writeValueAsString(requestBody);
        } catch (Exception e) {
            throw new IOException("序列化作品请求参数失败", e);
        }

        try {
            // 使用作品重试决策器（增强版）
            String response = httpRequestUtil.sendRequest(
                    userPostUrl,
                    "POST",
                    headers,
                    requestJson,
                    createWorkRetryDecision(new WbWorksData()) // 传入重试决策器
            );

            if (response == null || response.trim().isEmpty()) {
                log.warn("微博用户 {} 作品请求返回空响应", userId);
                return null;
            }

            long responseTime = System.currentTimeMillis() - startTime;
            log.info("微博用户 {} 作品请求完成，响应时间: {}ms", userId, responseTime);
            return response;

        } catch (Exception e) {
            long responseTime = System.currentTimeMillis() - startTime;
            log.error("微博用户 {} 请求异常（{}ms）: {}", userId, responseTime, e.getMessage());
            return null;
        }
    }

    /**
     * 解析单页作品数据（依赖重试决策器校验节点）
     */
    private List<WbWorksData> parseWorksPage(String response, WbUserInfo user, String nowTime) {
        List<WbWorksData> resultList = new ArrayList<>();
        if (response == null || response.trim().isEmpty()) {
            return resultList;
        }

        try {
            // 获取作品列表长度
            Integer cardsLength = JsonParserUtils.getListLength(response, "data.data.cards");
            if (cardsLength == null || cardsLength <= 0) {
                return resultList;
            }

            // 遍历解析每个作品
            for (int i = 0; i < cardsLength; i++) {
                String cardPath = "data.data.cards[" + i + "]";

                // 只处理类型为9的卡片（微博正文）
                Integer cardType = JsonParserUtils.getIntValueFromString(response, cardPath + ".card_type");
                if (cardType == null || cardType != 9) {
                    continue;
                }

                // 解析微博内容节点
                String mblogPath = cardPath + ".mblog";
                Boolean hasMblog = JsonParserUtils.isNodeValid(response, mblogPath);
                if (hasMblog == null || !hasMblog) {
                    log.warn("第{}个作品缺少mblog节点，跳过", i + 1);
                    continue;
                }

                WbWorksData work = parseSingleWork(response, mblogPath, user, nowTime);
                if (work != null) {
                    resultList.add(work);
                }
            }
        } catch (Exception e) {
            log.error("解析作品列表失败", e);
        }

        return resultList;
    }

    /**
     * 解析单个作品数据（使用统一时间戳）
     */
    private WbWorksData parseSingleWork(String response, String mblogPath, WbUserInfo user, String nowTime) {
        WbWorksData work = new WbWorksData();
        work.setId(JsonParserUtils.getStringValueFromString(response, mblogPath + ".id"));
        work.setUserId(user.getId());
        work.setUpdateTime(nowTime); // 使用统一更新时间

        // 基础信息
        work.setText(JsonParserUtils.getStringValueFromString(response, mblogPath + ".text"));

        // 时间处理
        String createdAt = JsonParserUtils.getStringValueFromString(response, mblogPath + ".created_at");
        work.setCreateTime(DateTimeUtil.formatWeiboTime(createdAt));

        // 互动数据
        work.setRepostsCount(JsonParserUtils.getIntValueFromString(response, mblogPath + ".reposts_count"));
        work.setCommentsCount(JsonParserUtils.getIntValueFromString(response, mblogPath + ".comments_count"));
        work.setAttitudesCount(JsonParserUtils.getIntValueFromString(response, mblogPath + ".attitudes_count"));

        return work;
    }

    /**
     * 解析下一页游标
     */
    private String parseSinceId(String response) {
        try {
            return JsonParserUtils.getStringValueFromString(response, "data.data.cardlistInfo.since_id");
        } catch (Exception e) {
            log.warn("解析since_id失败", e);
            return null;
        }
    }

    /**
     * 解析粉丝数（处理"万"、"亿"单位）
     */
    private long parseFollowersCount(String countStr) {
        if (countStr == null || countStr.isEmpty()) {
            return 0L;
        }

        try {
            if (countStr.contains("亿")) {
                return (long) (Double.parseDouble(countStr.replace("亿", "")) * 100000000);
            } else if (countStr.contains("万")) {
                return (long) (Double.parseDouble(countStr.replace("万", "")) * 10000);
            }
            return Long.parseLong(countStr);
        } catch (NumberFormatException e) {
            log.warn("粉丝数转换失败: 原始值={}", countStr);
            return 0L;
        }
    }

    // ========================== PlatformHandler接口实现 ==========================

    /**
     * 返回微博平台类型编码
     */
    @Override
    public String getPlatformType() {
        return PlatformType.WEIBO.getCode();
    }

    /**
     * 获取本地系统中已有的微博用户数据
     */
    @Override
    public List<?> fetchExternalData() {
        List<WbUserInfo> localUserList = userInfoMapper.getUserInfos();
        if (localUserList == null) {
            log.warn("本地微博用户表查询返回null，返回空列表");
            return new ArrayList<>();
        }
        log.info("从本地微博用户表获取到 {} 条已有数据", localUserList.size());
        return localUserList;
    }

    /**
     * 从本地用户数据中提取微博账号唯一标识
     */
    @Override
    public String extractAccountId(Object data) {
        if (data == null || !(data instanceof WbUserInfo)) {
            log.warn("本地用户数据格式无效，无法提取账号ID");
            return null;
        }
        WbUserInfo localUser = (WbUserInfo) data;
        return localUser.getId();
    }

    /**
     * 校验账号有效性（使用增强的重试决策器）
     */
    @Override
    public boolean verifyAccount(PlatformAccount account) {
        if (account == null || account.getAccountId() == null || account.getAccountId().trim().isEmpty()) {
            log.warn("待校验账号信息无效（ID为空）");
            return false;
        }

        String uid = account.getAccountId().trim();
        WbUserInfo userInfo = new WbUserInfo();
        userInfo.setUserId(uid);

        Map<String, String> headers = createHeaders(userInfo);

        try {
            String requestBody = buildUserRequestData(userInfo);
            if (requestBody == null) {
                log.error("构建账号校验请求报文失败");
                return false;
            }

            // 使用用户重试决策器校验
            String response = httpRequestUtil.sendRequest(
                    getUserApiUrl(userInfo),
                    getUserRequestMethod(),
                    headers,
                    requestBody,
                    createUserRetryDecision(userInfo)
            );

            if (response == null || response.trim().isEmpty()) {
                log.warn("账号[{}]校验失败：响应为空", uid);
                return false;
            }

            log.info("账号[{}]校验成功：在微博真实存在", uid);
            return true;
        } catch (Exception e) {
            log.error("账号[{}]校验失败：微博API请求异常", uid, e);
            return false;
        }
    }

    /**
     * 将校验通过的账号同步到本地微博用户表
     */
    @Override
    public void writeToExternalSystem(PlatformAccount account) {
        if (account == null || account.getAccountId() == null || account.getAccountId().trim().isEmpty()) {
            log.warn("待同步账号信息无效（ID为空）");
            return;
        }

        String uid = account.getAccountId().trim();
        String nowTime = DateTimeUtil.getCurrentTimestamp();
        WbUserInfo userInfo = new WbUserInfo();

        userInfo.setUserId(uid);
        userInfo.setCreateTime(account.getCreateTime());
        userInfo.setUpdateTime(nowTime);
        userInfo.setState(account.getState());
        userInfo.setId(account.getId());

        userInfoMapper.insert(userInfo);
        log.info("账号[{}]已同步到本地微博用户表", uid);
    }

    @Override
    public String verifyAddedAccount(PlatformAccount account) {
        if (null == account.getAccountId() || account.getAccountId().trim().isEmpty()) {
            return "微博账号的accountId不能为空";
        }

        QueryWrapper<PlatformAccount> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("platform_type", account.getPlatformType());
        queryWrapper.eq("account_id",account.getAccountId());

        int count = platformAccountService.count(queryWrapper);
        if (count > 0) {
            return "微博账号的accountId账号已存在";
        }

        return null;
    }
}
